package com.sunny.ihealth.data;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.sunny.ihealth.entity.bmob.Comment;
import com.sunny.ihealth.entity.bmob.Post;
import com.sunny.ihealth.entity.bmob.State;
import com.sunny.ihealth.entity.bmob.UserInfo;
import com.sunny.ihealth.entity.bmob.UserRelation;
import com.sunny.ihealth.utils.NetworkUtils;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import cn.bmob.v3.AsyncCustomEndpoints;
import cn.bmob.v3.Bmob;
import cn.bmob.v3.BmobQuery;
import cn.bmob.v3.BmobUser;
import cn.bmob.v3.datatype.BmobFile;
import cn.bmob.v3.datatype.BmobQueryResult;
import cn.bmob.v3.exception.BmobException;
import cn.bmob.v3.listener.CloudCodeListener;
import cn.bmob.v3.listener.FindListener;
import cn.bmob.v3.listener.SQLQueryListener;
import cn.bmob.v3.listener.SaveListener;
import cn.bmob.v3.listener.UpdateListener;
import cn.bmob.v3.listener.UploadBatchListener;
import cn.bmob.v3.listener.UploadFileListener;

/**
 * Bmob功能管理类
 * Created by Sunny  An on 2016/5/13.
 */
public class BmobManager {

    /**
     * 一个参数的接口
     *
     * @param <T>
     */
    public interface Action1<T> {
        void onCompleted(T t);
    }

    /**
     * 两个参数的接口
     *
     * @param <T>
     * @param <R>
     */
    public interface Action2<T, R> {
        void onCompleted(T t, R r);
    }

    private static final String TAG = "BmobManager";
    private static final String APP_KEY = "2a656c520baa2e8302fd33fbf9b436e6";

    private Context context;
    private Handler handler;

    /**
     * 初始化Bmob
     */
    public BmobManager(Context context) {
        this.context = context;
        handler = new Handler(Looper.getMainLooper());
        Bmob.initialize(this.context, APP_KEY);
    }

    /**
     * 获取错误提示信息
     */
    private String getErrorMessage(int position, int i, String s) {
        String msg = format("error at:%d\ncode:%d\nmessage:%s", position, i, s);
        Log.e(TAG, msg);
        return msg;
    }

    private String format(String format, Object... args) {
        return String.format(Locale.getDefault(), format, args);
    }

    /**
     * 错误toast
     *
     * @param position 位置
     * @param code     错误代码
     * @param s        错误信息
     */
    private void toast(int position, int code, String s) {
        String message;
        switch (code) {
            case 1:
                message = "SDK内部产生错误,请联系我...";
                break;
            case 202:
                message = "账号已存在，换一个账号吧~";
                break;
            case 101:
                message = "账号或密码不正确~";
                break;
            case 9010:
            case 141:
                message = "网速太慢啦,连接超时~";
                break;
            case 9016:
            case 9015:
                message = "网络不可用，请检查~";
                break;
            default:
                Toast.makeText(context, getErrorMessage(position, code, s), Toast.LENGTH_SHORT).show();
                return;
        }
        Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
        //打印错误日志
        getErrorMessage(position, code, s);
    }


    /**
     * 注册账号
     */
    public void registerUser(final String username, final String password, final Action1<Boolean> listener) {

        final UserInfo user = new UserInfo();
        user.setFriendNumber(0);
        user.setFansNumber(0);
        user.setUsername(username);
        user.setPassword(password);
        user.setNickname(username);
        user.setSignature("这家伙很懒，什么都没留下...");
        user.setGender(UserInfo.GENDER_MALE);
        user.signUp(context, new SaveListener() {
            @Override
            public void onSuccess() {
                listener.onCompleted(true);
            }

            @Override
            public void onFailure(int i, String s) {
                toast(1, i, s);
                listener.onCompleted(false);
            }
        });

    }


    /**
     * 用户登陆
     * 失败UserInfo = null
     */
    public void login(String username, String password, final Action1<UserInfo> listener) {
        UserInfo user = new UserInfo();
        user.setUsername(username);
        user.setPassword(password);
        user.login(context, new SaveListener() {
            @Override
            public void onSuccess() {
                listener.onCompleted(UserInfo.getCurrentUser(context, UserInfo.class));
            }

            @Override
            public void onFailure(int i, String s) {
                toast(2, i, s);
                listener.onCompleted(null);
            }
        });
    }


    /**
     * 下线当前账号
     */
    public void logout() {
        BmobUser.logOut(context);
    }

    /**
     * 检查用户状态
     *
     * @return 登陆成功或者有网络返回true
     */
    public boolean checkState() {
        UserInfo user = BmobUser.getCurrentUser(context, UserInfo.class);
        if (user == null || TextUtils.isEmpty(user.getObjectId())) {
            Toast.makeText(context, "请先登录~", Toast.LENGTH_SHORT).show();
            return false;
        }
        return NetworkUtils.isNetworkAvailable(context, true);
    }


    /**
     * 更新用户资料
     */
    public void updateUserInfo(final String nickname, final String signature, final boolean gender, final Action1<UserInfo> listener) {
        final UserInfo user = BmobUser.getCurrentUser(context, UserInfo.class);
        if (user != null && !TextUtils.isEmpty(user.getObjectId())) {
            final UserInfo newInfo = new UserInfo();
            newInfo.setNickname(nickname);
            newInfo.setSignature(signature);
            newInfo.setGender(gender);
            newInfo.update(context, user.getObjectId(), new UpdateListener() {
                @Override
                public void onSuccess() {
                    listener.onCompleted(UserInfo.getCurrentUser(context, UserInfo.class));
                }

                @Override
                public void onFailure(int i, String s) {
                    toast(3, i, s);
                    listener.onCompleted(null);
                }
            });
        } else {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    toast(4, 4, "获取当前帐号失败");
                    listener.onCompleted(null);
                }
            });
        }
    }


    /**
     * 上传用户头像
     */
    public void updateUserHeadFile(final String filePath, final Action1<UserInfo> listener) {
        final UserInfo user = BmobUser.getCurrentUser(context, UserInfo.class);
        if (user != null && !TextUtils.isEmpty(user.getObjectId())) {
            final BmobFile bmobFile = new BmobFile(new File((filePath)));
            bmobFile.uploadblock(context, new UploadFileListener() {
                @Override
                public void onSuccess() {
                    final UserInfo newInfo = new UserInfo();
                    newInfo.setHeadFile(bmobFile);
                    newInfo.update(context, user.getObjectId(), new UpdateListener() {
                        @Override
                        public void onSuccess() {
                            listener.onCompleted(UserInfo.getCurrentUser(context, UserInfo.class));
                        }

                        @Override
                        public void onFailure(int i, String s) {
                            toast(5, i, s);
                            listener.onCompleted(null);
                        }
                    });
                }

                @Override
                public void onFailure(int i, String s) {
                    toast(6, i, s);
                    listener.onCompleted(null);
                }
            });
        } else {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    toast(7, 7, "获取当前帐号失败");
                    listener.onCompleted(null);
                }
            });
        }
    }


    /**
     * 发送一篇帖子
     *
     * @param content  内容
     * @param listener 监听器
     */
    public void publishPost(String content, final Action1<Boolean> listener) {
        final UserInfo user = BmobUser.getCurrentUser(context, UserInfo.class);
        if (user != null && !TextUtils.isEmpty(user.getObjectId())) {
            Post post = new Post();
            post.setAuthor(user);
            post.setContent(content);
            post.setCommentNumber(0);
            post.setLikeNumber(0);

            post.save(context, new SaveListener() {
                @Override
                public void onSuccess() {
                    listener.onCompleted(true);
                }

                @Override
                public void onFailure(int i, String s) {
                    toast(7, i, s);
                    listener.onCompleted(false);
                }
            });

        } else {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    toast(8, 8, "帖子发送失败");
                    listener.onCompleted(false);
                }
            });
        }
    }


    /**
     * 发送带图片的帖子
     *
     * @param listener 图片上传失败，将调用listener(false,-1)   帖子发送失败，调用listener(false,-2)
     */
    public void publishPost(final String content, List<String> pictures, final Action2<Boolean, Integer> listener) {
        final UserInfo user = BmobUser.getCurrentUser(context, UserInfo.class);
        if (user != null && !TextUtils.isEmpty(user.getObjectId())) {
            //上传图片
            final String[] picPaths = new String[pictures.size()];
            pictures.toArray(picPaths);
            BmobFile.uploadBatch(context, picPaths, new UploadBatchListener() {
                @Override
                public void onSuccess(List<BmobFile> files, List<String> urls) {
                    listener.onCompleted(false, urls.size());
                    if (urls.size() == picPaths.length) {
                        publishPostWithPictures(content, files, listener);
                    }
                }

                @Override
                public void onProgress(int i, int i1, int i2, int i3) {

                }

                @Override
                public void onError(int i, String s) {
                    toast(9, i, s);
                    listener.onCompleted(false, -1);
                }
            });

        } else {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    toast(10, 10, "图片上传失败");
                    listener.onCompleted(false, -1);
                }
            });
        }
    }


    /**
     * 上传文件成功后，发送帖子
     */
    private void publishPostWithPictures(String content, final List<BmobFile> files, final Action2<Boolean, Integer> listener) {
        if (!checkState()) {
            return;
        }
        Post post = new Post();
        post.setAuthor(BmobUser.getCurrentUser(context, UserInfo.class));
        post.setContent(content);
        post.setCommentNumber(0);
        post.setLikeNumber(0);
        post.setPictures(files);
        post.save(context, new SaveListener() {
            @Override
            public void onSuccess() {
                listener.onCompleted(true, files.size());
            }

            @Override
            public void onFailure(int i, String s) {
                toast(11, i, s);
                listener.onCompleted(false, -2);
            }
        });
    }


    /**
     * 获取所有的帖子信息
     *
     * @param skip     跳过数据 从0开始
     * @param limit    显示多少
     * @param beforeID 哪个id之后的帖子
     * @param listener 监听器
     */
    public void getPost(final int skip, int limit, Integer beforeID, final Action1<List<Post>> listener) {
        JSONObject jsonObject = new JSONObject();
        UserInfo user = BmobUser.getCurrentUser(context, UserInfo.class);
        try {
            if (user != null && !TextUtils.isEmpty(user.getObjectId())) {
                jsonObject.put("userID", user.getObjectId());
            }

            if (beforeID != null) {
                jsonObject.put("beforeID", beforeID);
            }
            jsonObject.put("skip", skip);
            jsonObject.put("limit", limit);
        } catch (JSONException e) {
            e.printStackTrace();
        }

        AsyncCustomEndpoints ace = new AsyncCustomEndpoints();
        ace.callEndpoint(context, "getPost", jsonObject, new CloudCodeListener() {
            @Override
            public void onSuccess(Object o) {
                List<Post> data = new ArrayList<>();
                try {
                    data = new Gson().fromJson(o.toString(), new TypeToken<ArrayList<Post>>() {
                    }.getType());
                } catch (Exception ignored) {
                }
                listener.onCompleted(data);
            }

            @Override
            public void onFailure(int i, String s) {
                listener.onCompleted(null);
                toast(12, i, s);
            }
        });

    }


    /**
     * 获取所有的帖子信息
     *
     * @param watchUserID 看谁的帖子
     * @param skip        跳过数据 从0开始
     * @param limit       显示多少
     * @param beforeID    哪个id之后的帖子
     * @param listener    监听器
     */
    public void getPost(String watchUserID, final int skip, int limit, Integer beforeID, final Action1<List<Post>> listener) {
        JSONObject jsonObject = new JSONObject();
        UserInfo user = BmobUser.getCurrentUser(context, UserInfo.class);
        try {
            if (user != null && !TextUtils.isEmpty(user.getObjectId())) {
                jsonObject.put("userID", user.getObjectId());
            }

            if (beforeID != null) {
                jsonObject.put("beforeID", beforeID);
            }
            jsonObject.put("watchUserID", watchUserID);
            jsonObject.put("skip", skip);
            jsonObject.put("limit", limit);
        } catch (JSONException e) {
            e.printStackTrace();
        }

        AsyncCustomEndpoints ace = new AsyncCustomEndpoints();
        ace.callEndpoint(context, "getUserPost", jsonObject, new CloudCodeListener() {
            @Override
            public void onSuccess(Object o) {
                List<Post> data = new ArrayList<>();
                try {
                    data = new Gson().fromJson(o.toString(), new TypeToken<ArrayList<Post>>() {
                    }.getType());
                } catch (Exception ignored) {
                }
                listener.onCompleted(data);
            }

            @Override
            public void onFailure(int i, String s) {
                listener.onCompleted(null);
                toast(13, i, s);
            }
        });

    }


    /**
     * 喜欢一个帖子
     *
     * @param postID 帖子的ID
     */
    public void likePost(String postID, final Action1<State> listener) {
        final State state = new State();
        if (!checkState()) {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    state.setState(State.STATE_OTHER_FAILED);
                    listener.onCompleted(state);
                }
            });
            return;
        }

        final JSONObject jsonObject = new JSONObject();
        try {
            jsonObject.put("userID", BmobUser.getCurrentUser(context, UserInfo.class).getObjectId());
            jsonObject.put("postID", postID);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        AsyncCustomEndpoints ace = new AsyncCustomEndpoints();
        ace.callEndpoint(context, "likePost", jsonObject, new CloudCodeListener() {
            @Override
            public void onSuccess(Object o) {
                listener.onCompleted(new Gson().fromJson(o.toString(), State.class));
            }

            @Override
            public void onFailure(int i, String s) {
                toast(14, i, s);
                state.setState(State.STATE_OTHER_FAILED);
                listener.onCompleted(state);
            }
        });
    }


    /**
     * 获取某一个动态的评论
     *
     * @param postID   帖子id
     * @param skip     跳过多少
     * @param limit    显示多少
     * @param beforeID 在哪个id之后的数据
     * @param listener 监听器
     */
    public void getComment(String postID, final int skip, final int limit, Integer beforeID, final Action1<List<Comment>> listener) {

        //获取评论
        String id;
        if (beforeID == null) {
            id = "";
        } else {
            id = format("and id < %d", beforeID);
        }
        String sql = format("select include author,author,content,id from Comment where post=pointer('Post','%s') %s order by createdAt desc limit %d,%d",
                postID, id, skip, limit);
        new BmobQuery<Comment>().doSQLQuery(context, sql, new SQLQueryListener<Comment>() {
            @Override
            public void done(BmobQueryResult<Comment> bmobQueryResult, BmobException e) {
                List<Comment> data = new ArrayList<>();
                if (e != null) {
                    toast(15, e.getErrorCode(), e.getMessage());
                } else {
                    data = bmobQueryResult.getResults() == null ? data : bmobQueryResult.getResults();
                }
                ;
                listener.onCompleted(data);
            }
        });


    }


    /**
     * 发表评论
     *
     * @param postID   帖子id
     * @param content  评论内容
     * @param listener 监听器
     */
    public void publishComment(String postID, String content, final Action1<Comment> listener) {
        if (!checkState()) {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    listener.onCompleted(null);
                }
            });
            return;
        }

        final Comment comment = new Comment();
        comment.setAuthor(BmobUser.getCurrentUser(context, UserInfo.class));
        final Post post = new Post();
        post.setObjectId(postID);
        comment.setPost(post);
        comment.setContent(content);

        comment.save(context, new SaveListener() {
            @Override
            public void onSuccess() {
                post.increment("commentNumber", 1);
                post.update(context);
                listener.onCompleted(comment);
            }

            @Override
            public void onFailure(int i, String s) {
                toast(16, i, s);
                listener.onCompleted(null);
            }
        });
    }


    /**
     * 添加好友
     *
     * @param friendID 帖子的ID
     */
    public void addFriend(String friendID, final Action1<State> listener) {
        UserInfo user = BmobUser.getCurrentUser(context, UserInfo.class);
        final State state = new State();
        state.setState(State.STATE_OTHER_FAILED);

        boolean isMyself = user != null && user.getObjectId().equals(friendID);
        if (isMyself || !checkState()) {
            if (isMyself) {
                Toast.makeText(context, "不能关注自己~", Toast.LENGTH_SHORT).show();
            }
            handler.post(new Runnable() {
                @Override
                public void run() {
                    listener.onCompleted(state);
                }
            });
            return;
        }

        final JSONObject jsonObject = new JSONObject();
        try {
            jsonObject.put("userID", user.getObjectId());
            jsonObject.put("friendID", friendID);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        AsyncCustomEndpoints ace = new AsyncCustomEndpoints();
        ace.callEndpoint(context, "addFriend", jsonObject, new CloudCodeListener() {
            @Override
            public void onSuccess(Object o) {
                listener.onCompleted(new Gson().fromJson(o.toString(), State.class));
            }

            @Override
            public void onFailure(int i, String s) {
                toast(17, i, s);
                listener.onCompleted(state);
            }
        });
    }


    /**
     * 获取好友或粉丝
     *
     * @param getFriend 获取好友true   获取粉丝false
     * @param listener  监听器
     */
    public void getFriends(boolean getFriend, final Action1<List<UserRelation>> listener) {
        if (!checkState()) {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    listener.onCompleted(null);
                }
            });
            return;
        }

        BmobQuery<UserRelation> query = new BmobQuery<>();
        UserInfo userInfo = new UserInfo();
        userInfo.setObjectId(BmobUser.getCurrentUser(context, UserInfo.class).getObjectId());
        if (getFriend) {
            query.addWhereEqualTo("user", userInfo);
            query.include("friend");
        } else {
            query.addWhereEqualTo("friend", userInfo);
            query.include("user");
        }
        query.setLimit(1000);
        query.findObjects(context, new FindListener<UserRelation>() {
            @Override
            public void onSuccess(List<UserRelation> list) {
                listener.onCompleted(list);
            }

            @Override
            public void onError(int i, String s) {
                toast(18, i, s);
                listener.onCompleted(null);
            }
        });
    }


}
